home *** CD-ROM | disk | FTP | other *** search
- /*
-
- MercuryInstaller テキストビュワールーチン
-
- */
-
- #include<stdio.h>
- #include<stdlib.h>
- #include<jctype.h>
- #include<string.h>
- #include<jstring.h>
- #include<farstr.h>
- #include<dos.h>
- #include<stdarg.h>
-
- #include<LHACCESS.H>
- #include"mercury.h"
- /*===========================================================================*/
- /* 定数と変数 */
- /*===========================================================================*/
- #define TEXT_STARTYPOS 3 /* テキスト表示開始位置 */
- #define TEXT_YWIDTH (CON_YWIDTH-TEXT_STARTYPOS)
- /* テキスト表示行数(putmessage専用行は除いてある) */
-
- static char far **Text; /* テキストバッファ */
- static int Linenum; /* テキストの総行数 */
- static int Linepos; /* 現在表示中の内容の開始行番号 */
- static int Bufsize; /* バッファの行数 */
- /*===========================================================================*/
- /* ファイル読み込み関連 */
- /*===========================================================================*/
-
- /*------------------------------メモリの確保---------------------------------*/
- /* まず指定容量のメモリの確保を試み、失敗した場合は少しずつ容量を減らしてゆく*/
- /*---------------------------------------------------------------------------*/
- static void *nearcalloc_down(size_t num,size_t width,size_t *ret)
- {
- void *p;
-
- while ((p=calloc(num,width))==NULL && num>1)
- num--;
-
- if (p==NULL)
- *ret = 0;
- else
- *ret = num;
-
- return p;
- }
-
- static void far *maxfarmalloc(long *size)
- {
- long s = farcoreleft();
- void far *p;
-
- do
- {
- p = farmalloc(s);
- if (p!=NULL)
- {
- *size = s;
- return p;
- }
- } while(--s);
-
- return NULL;
- }
-
- /*-----------------------------仮想ファイルの処理----------------------------*/
- /* LHACCESSライブラリを経由した書庫ファイルか、それとも単なるベタテキストかを*/
- /* 全く意識せずに使用するためのルーチン */
- /*---------------------------------------------------------------------------*/
- static struct
- {
- enum {NONE,LZH,TEXT} mode;
- union
- {
- FILE *fp;
- ROOT root;
- } pointer;
- } File;
-
- static int File_ungetc;
-
- static void file_open(char *filename)
- {
- char *p = jstrchr(filename,'|');
-
- File_ungetc = EOF;
-
- if (p!=NULL) /* 書庫ファイルを通したアクセス */
- {
- *p = '\0';
-
- if (islzh(filename)!=0 ||
- open_root(filename,&File.pointer.root)!=0)
- {
- *p = '|';
- goto error;
- }
-
- *p = '|';
-
- if (get_all_header(&File.pointer.root)!=0 ||
- lzh_fopen2(&File.pointer.root,p+1)!=0 )
- {
- close_root(&File.pointer.root);
- goto error;
- }
-
- File.mode = LZH;
- return;
- }
- else
- {
- if ((File.pointer.fp=fopen(filename,"r"))==NULL)
- goto error;
-
- File.mode = TEXT;
- return;
- }
- error:
- File.mode = NONE;
- return;
- }
-
- static void file_close(void)
- {
- switch (File.mode)
- {
- case LZH:
- close_root(&File.pointer.root);
- break;
- case TEXT:
- fclose(File.pointer.fp);
- break;
- }
- }
-
- static int file_getc(void)
- {
- int c;
-
- if (File_ungetc!=EOF)
- {
- c = File_ungetc;
- File_ungetc = EOF;
- return c;
- }
- switch (File.mode)
- {
- case NONE:
- return EOF;
-
- case LZH:
- do
- c = lzh_fgetc();
- while (c=='\r' || c=='\x1a');
-
- return c;
-
- case TEXT:
- return fgetc(File.pointer.fp);
- }
- }
-
- #define file_ungetc(c) (File_ungetc=(c))
- /*---------------------------テキストの読み込み------------------------------*/
- static bool readfile(char *filename)
- {
- char far *p;
- int xlen=0;
- int c;
- int isknj = 0;
- long bufsize,buf_left;
-
- file_open(filename);
-
- Linenum = 0;
-
- Text = nearcalloc_down(4096,sizeof(char far *),&Bufsize);
- if (Text==NULL)
- {
- putmessage("メモリ不足です");
- return 0;
- }
-
- p = Text[0] = maxfarmalloc(&bufsize);
- buf_left = bufsize;
-
- while ((c=file_getc())!=EOF)
- {
- *p++ = c;
- buf_left--;
-
- if (c=='\t')
- xlen += CON_TABSIZE - xlen%CON_TABSIZE;
- else
- xlen++;
-
- if (!isknj && iskanji(c))
- isknj = 1;
- else
- isknj = 0;
-
- if (xlen>=CON_XWIDTH || c=='\n')
- {
- if (isknj)
- {
- file_ungetc(c);
- p--;
- buf_left++;
- isknj = 0;
- }
-
- *p = '\0';
- xlen = 0;
-
- if (++Linenum == Bufsize)
- {
- putmessage("行数が多すぎるので途中で打ち切ります");
- break;
- }
-
- p += 1L;
- Text[Linenum] = p;
- buf_left--;
- }
-
- if (buf_left<2)
- {
- putmessage("メモリ不足です 途中で打ち切ります;bufsize=%ld,buf_left=%ld",bufsize,buf_left);
- break;
- }
- }
-
- if (xlen)
- {
- *p = '\0';
- Linenum++;
- }
-
- if (Linenum==0)
- {
- farfree(Text[0]);
- free(Text);
- }
- else
- {
- farrealloc(Text[0],bufsize-buf_left);
- realloc(Text,Linenum*sizeof(Text[0]));
- }
- file_close();
- return 1;
- }
- /*--------------------------ファイルバッファの解放---------------------------*/
- static void memory_release(void)
- {
- if (Linenum>0)
- {
- farfree(Text[0]);
- free(Text);
- }
- }
- /*-----------------------------パス名の生成----------------------------------*/
- static void mkpath(char *buf,char far *dir,char far *filename)
- {
- if (dir==NULL || filename[1]==':')
- buf[0] = '\0';
- else
- {
- buf[0] = Drive;
- buf[1] = ':';
- if (filename[0]!='\\')
- {
- if (dir!=NULL)
- far_strcpy(buf+2,dir);
- else
- buf[2] = '\0';
-
- strcat(buf,"\\");
- }
- else
- buf[2] = '\0';
- }
-
- far_strcat(buf,filename);
- }
- /*-----------------------------ファイルの検索--------------------------------*/
- /* ○指定されたディレクトリからファイルを検索し、最初に見つかったファイルの */
- /* ファイル名をbufに返す。 */
- /* ○ファイルが見つからない場合は、bufに空文字列をセットする。 */
- /* ○なお、dirはDataから引っ張ってくる関係でfarポインタになっている。 */
- /*---------------------------------------------------------------------------*/
- static bool findfile(char far *dir,char *wildcard,char buf[])
- {
- char *p;
- struct find_t fib;
-
- mkpath(buf,dir,wildcard);
-
- if ((p=jstrrchr(buf,'\\'))!=NULL)
- p++;
- else if (buf[1]==':')
- p = buf+2;
- else
- p = buf;
-
- if (_dos_findfirst(buf,_A_NORMAL,&fib)==0)
- {
- strcpy(p,fib.name);
- return 1;
- }
- else
- {
- buf[0] = '\0';
- return 0;
- }
- }
-
- /*===========================================================================*/
- /* 画面表示関連(1):テキストのスクロール */
- /*===========================================================================*/
-
- /*----------------------------------行を表示---------------------------------*/
- static void showoneline(int ypos)
- {
- printf("\033[%d;1f\033[2K",ypos+TEXT_STARTYPOS);
-
- if (Linepos+ypos>=Linenum)
- return;
-
- far_fputs(Text[Linepos+ypos],stdout);
- }
- /*---------------------画面全体の表示(インライン関数)------------------------*/
- #define showtext() do \
- { \
- int i; \
- \
- for (i=0 ; i<TEXT_YWIDTH ; i++) \
- showoneline(i); \
- } while(0)
- /*-------------------------------画面の初期化--------------------------------*/
- static void screen_init(char far *title,char *filename)
- {
- static char far *title_save;
- static char *filename_save;
- char buf[TITLEWIDTH+1];
-
- if (title==NULL)
- title = title_save;
- else
- title_save = title;
-
- if (filename==NULL)
- filename = filename_save;
- else
- filename_save = filename;
-
- far_strcpy(buf,title);
- printf("\033[2J\033[7;36m%-*s\033[37;7m%-*s\n",TITLEWIDTH,buf,
- CON_XWIDTH-TITLEWIDTH," [F5]HELP");
- printf("\033[2;1f\033[7;36m%-*s\033[0m",CON_XWIDTH,filename);
-
- showtext();
- }
- /*-----------------------------画面のスクロール------------------------------*/
- static void scrolldown(void)
- {
- if (Linepos==Linenum-1)
- return;
-
- Linepos++;
-
- printf("\033[%d;1f",TEXT_STARTYPOS);
-
- if (Flag_isfmesc) printf("\033R");
- else printf("\033[M");
-
- showoneline(TEXT_YWIDTH-1);
- }
-
- static void scrollup(void)
- {
- if (Linepos==0)
- return;
-
- Linepos--;
-
- printf("\033[%d;1f",TEXT_STARTYPOS);
-
- if (Flag_isfmesc) printf("\033E");
- else printf("\033[L");
-
- printf("\033[%d;1f\033[2K",TEXT_STARTYPOS+TEXT_YWIDTH);
-
- showoneline(0);
- }
-
- /*===========================================================================*/
- /* 画面表示関連(2):ウィンドウシステムライブラリ */
- /*===========================================================================*/
- /* これらの関数はtextviewer()の下でしか使えないので要注意。 */
- /*===========================================================================*/
-
- static struct
- {
- int xstart,ystart; /* 文字表示開始xy座標 */
- int xsize,ysize; /* ウィンドウのサイズ */
- } Window;
-
- /*-----------------------------ウィンドウを開く------------------------------*/
- extern void openwindow(int ysize,int xsize)
- {
- int i;
-
- Window.ysize = ysize;
- Window.xsize = xsize;
-
- Window.xstart = (CON_XWIDTH-xsize)/2;
- Window.ystart = (CON_YWIDTH-ysize)/2;
-
- printf("\033[%d;%df\033[36m+",Window.ystart-1,Window.xstart-1);
- for (i=0 ; i<Window.xsize ; i++)
- putchar('-');
-
- printf("+\033[%d;%df+",Window.ystart+Window.ysize,Window.xstart-1);
- for (i=0 ; i<Window.xsize ; i++)
- putchar('-');
-
- putchar('+');
-
- for (i=0 ; i<Window.ysize ; i++)
- {
- printf("\033[%d;%df|%*s|",Window.ystart+i,Window.xstart-1,
- Window.xsize,"");
- }
-
- printf("\033[0m");
- }
- /*----------------------------ウィンドウを閉じる-----------------------------*/
- extern void closewindow(void)
- {
- int i;
-
- for (i=-1 ; i<=Window.ysize ; i++)
- showoneline(Window.ystart+i-TEXT_STARTYPOS);
- }
- /*--------------------------------文字列の出力-------------------------------*/
- /* ウィンドウの各行の最後の1バイトは全角文字の禁則処理専用に予約済。 */
- /*---------------------------------------------------------------------------*/
- extern void window_putstr(int ypos,char *format,...)
- {
- va_list ap;
- char buf[256];
- char *p = buf;
- char c;
- int xpos = 0;
-
- va_start(ap,format);
- vsprintf(buf,format,ap);
-
- while ((c=*p++)!='\0')
- {
- if (xpos==0)
- printf("\033[%d;%df%*s\033[%d;%df",
- Window.ystart+ypos,Window.xstart,
- Window.xsize,"",
- Window.ystart+ypos,Window.xstart);
-
- putchar(c);
- xpos++;
-
- if (iskanji(c))
- {
- putchar(*p++);
- xpos++;
- }
-
- if (xpos>=Window.xsize-1 || c=='\n')
- {
- ypos++;
- xpos = 0;
- }
- }
- }
- /*-----------------------------文字列を入力する------------------------------*/
- /* 0<strlen(message)≦len≦CON_XWIDTH-5。ただしチェックはしない */
- /*---------------------------------------------------------------------------*/
- extern int window_strinput(char *message,char *buf,unsigned len)
- {
- int f;
-
- openwindow(2,len+3);
-
- window_putstr(0,"%s",message);
- window_putstr(1,"[%*s]",len,"");
-
- showcursor(1);
- printf("\033[%d;%df",Window.ystart+1,Window.xstart+1);
- f = ds_strinput(buf,len);
- showcursor(0);
-
- closewindow();
- return f;
- }
- /*---------------------選択肢を提示して入力を求める--------------------------*/
- /* messageは最大で64バイト×3行におさまること。ただしチェックはしない */
- /*---------------------------------------------------------------------------*/
- /* messageの後には、16個以下のconst char *が続く。たとえば"Abort"や"I:中止"の*/
- /* ように、先頭の1バイトは入力する際の文字ともなる。なお1行に収まるようにする*/
- /* こと */
- /*---------------------------------------------------------------------------*/
- extern int window_select(char *message,...)
- {
- char letter[16];
- char buf[256];
- char *p;
- int n=0;
- va_list ap;
-
- va_start(ap,message);
-
- openwindow(4,64);
- window_putstr(0,"%s",message);
-
- buf[0] = '\0';
-
- while ((p=va_arg(ap,char *))!=NULL)
- {
- strcat(buf,p);
- strcat(buf," ");
- letter[n++] = toupper(*p);
- }
-
- va_end(ap);
- window_putstr(3,"%s",buf);
-
- while (1)
- {
- int c = ds_getch();
- int i;
-
- if (c>=0x100)
- continue;
-
- c = toupper(c);
-
- for (i=0 ; i<n ; i++)
- {
- if (letter[i]==c)
- {
- closewindow();
- return c;
- }
- }
- }
- }
-
- /*===========================================================================*/
- /* 各種コマンド */
- /*===========================================================================*/
-
- /*-------------------印刷(厳密には他のファイルへの出力)----------------------*/
- static void printout(void)
- {
- static char filename[128] = "\\dev\\prn";
- char buf[128];
- FILE *fp;
- int i;
-
- strcpy(buf,filename);
- if (!window_strinput("印刷します 出力先デバイスを指定してください",buf,64))
- return;
-
- strcpy(filename,buf);
-
- openwindow(2,64);
-
- fp = fopen(filename,"w");
- if (fp==NULL)
- {
- window_putstr(0,"%sがオープンできません",filename);
- closewindow();
- return;
- }
-
- for (i=0 ; i<Linenum ; i++)
- {
- if (i%64==0)
- window_putstr(0,"出力中 %d/%d",i,Linenum);
-
- /* 中止の確認はint24Hハンドラがやってくれているはず */
- if (far_fputs(Text[i],fp))
- {
- window_putstr(0,"中止しました");
- goto error;
- }
- }
-
- window_putstr(0,"終了しました");
- error:
- ds_getch();
- closewindow();
- fclose(fp);
- }
- /*------------------------------ヘルプの出力---------------------------------*/
- static void helpmessage(void)
- {
- int i;
-
- static char *message[] =
- {
- "[↑][↓] スクロール",
- "[F1] 概要ファイル/マニュアル切り替え",
- "[F2] 現在見ているファイルの印刷",
- "[F3] インストール",
- "[F4] DOSコマンドライン",
- "[F5] ヘルプ(この画面)",
- "[ESC][F10] 終了",
- };
-
- openwindow(MEMBERSOF(message),64);
-
- for (i=0 ; i<MEMBERSOF(message) ; i++)
- window_putstr(i,message[i]);
-
- ds_getch();
- closewindow();
- }
-
- /*===========================================================================*/
- /* テキストビュワーのメインルーチン */
- /*===========================================================================*/
- extern void textviewer(struct DATA far *data)
- {
- char filename[2][256]; /* GGG/MANのファイル名 */
- bool ismanual = 0;
-
- if (data->readme!=NULL)
- mkpath(filename[0],data->dir,data->readme);
- else if (findfile(data->dir,"*.ggg" ,filename[0])) ;
- else if (findfile(data->dir,"!*.*" ,filename[0])) ;
- else if (findfile(data->dir,"read*.*",filename[0])) ;
- else if (findfile(data->dir,"*.doc" ,filename[0])) ;
-
- if (data->manual!=NULL)
- mkpath(filename[1],data->dir,data->manual);
- else if (findfile(data->dir,"*.rrr",filename[1])) ;
- else if (findfile(data->dir,"*.man",filename[1])) ;
- else if (findfile(data->dir,"*.doc",filename[1])) ;
-
- again:
- readfile(filename[ismanual]);
- Linepos = 0;
- screen_init(data->title,filename[ismanual]);
-
- while (1)
- {
- switch (ds_getch())
- {
- case FKEY_UP:
- scrollup();
- break;
- case FKEY_DOWN:
- scrolldown();
- break;
- case FKEY_LEFT:
- if ((Linepos-=TEXT_YWIDTH)<0)
- Linepos=0;
- showtext();
- break;
- case FKEY_RIGHT:
- if ((Linepos+=TEXT_YWIDTH)>=Linenum)
- Linepos = Linenum-1;
- showtext();
- break;
- case FKEY_F1:
- ismanual = !ismanual;
- memory_release();
- goto again;
- case FKEY_F2:
- printout();
- break;
- case FKEY_F3:
- installer(data);
- break;
- case FKEY_F4:
- showcursor(1);
- printf("\033[2J");
- system("");
- showcursor(0);
- screen_init(NULL,NULL);
- break;
- case FKEY_F5:
- helpmessage();
- break;
- case FKEY_F10:
- case FKEY_ESC:
- memory_release();
- return; /* 画面を元に戻すのは親関数の仕事 */
- }
- }
- }
- /*---------------------------End of textviewer.c-----------------------------*/